package bdsimple.impl.mysql;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import bdsimple.abstractfactory.AbstractFactoryDAO;
import bdsimple.dao.base.ArmaDAO;
import bdsimple.dao.base.ArmaduraDAO;
import bdsimple.dao.base.AvionDAO;
import bdsimple.dao.base.ItemDAO;
import bdsimple.dao.base.PocionDAO;
import bdsimple.dao.base.ProductoDAO;
import bdsimple.dto.base.ArmaDTO;
import bdsimple.dto.base.ArmaduraDTO;
import bdsimple.dto.base.AvionDTO;
import bdsimple.dto.base.ItemDTO;
import bdsimple.dto.base.PocionDTO;
import bdsimple.dto.base.PrecioItemCiudadDTO;
import bdsimple.dto.base.ProductoDTO;
import dao.base.api.IDTO;

public class ProductoDAOImpl extends MySQLBaseDAO implements ProductoDAO {

	public ProductoDAOImpl() {
		super(ProductoDTO.class);
		daoParentClass = ItemDAO.class;
	}

	//---------------------------------------------------------------------------
	@Override
	protected String createInsertCollst(IDTO dto) throws Exception {

		StringBuffer strbuf = new StringBuffer();

		strbuf.append(ProductoDTOImpl.ID);
		strbuf.append(", ");
		strbuf.append(ProductoDTOImpl.PRECIO_COMPRA);
		strbuf.append(", ");
		strbuf.append(ProductoDTOImpl.PRECIO_VENTA);

		return strbuf.toString();

	}

	//-------------------------------------------------------------------------------	
	@Override
	protected String createInsertValues(IDTO dto) throws Exception {

		ProductoDTOImpl productoDTOImpl = (ProductoDTOImpl) dto;

		StringBuffer strbuf = new StringBuffer();

		strbuf.append(productoDTOImpl.getId());
		strbuf.append(", ");
		strbuf.append(productoDTOImpl.getPrecioCompra());
		strbuf.append(", ");
		strbuf.append(productoDTOImpl.getPrecioVenta());

		return strbuf.toString();

	}

	//----------------------------------------------------------------------------------	
	@Override
	protected String createTableColumns() throws Exception {

		StringBuffer strbuf = new StringBuffer();

		strbuf.append(ProductoDTOImpl.ID);
		strbuf.append(" INT PRIMARY KEY, ");
		strbuf.append(ProductoDTOImpl.PRECIO_COMPRA);
		strbuf.append(" INT, ");
		strbuf.append(ProductoDTOImpl.PRECIO_VENTA);
		strbuf.append(" INT ");

		return strbuf.toString();

	}

	//-------------------------------------------------------------------------------------	
	@Override
	protected String createUpdateValues(IDTO dto) throws Exception {

		ProductoDTOImpl productoDTOImpl = (ProductoDTOImpl) dto;

		StringBuffer strbuf = new StringBuffer();

		strbuf.append(ProductoDTOImpl.PRECIO_COMPRA);
		strbuf.append(" = ");
		strbuf.append(productoDTOImpl.getPrecioCompra());

		strbuf.append(", ");

		strbuf.append(ProductoDTOImpl.PRECIO_VENTA);
		strbuf.append(" = ");
		strbuf.append(productoDTOImpl.getPrecioVenta());

		return strbuf.toString();
	}

	//-----------------------------------------------------------------------------------------	
	@Override
	protected ProductoDTOImpl internalResultSetToDTO(ResultSet rs, IDTO dto)
	throws Exception {

		ProductoDTOImpl ret = (ProductoDTOImpl) dto;

		ret.setId(rs.getInt(ProductoDTOImpl.ID));
		ret.setPrecioCompra(rs.getInt(ProductoDTOImpl.PRECIO_COMPRA));
		ret.setPrecioVenta(rs.getInt(ProductoDTOImpl.PRECIO_VENTA));

		return ret;

	}

	//------------------------------------------------------------------------------------------

	protected ProductoDTOImpl resultSetToDTO(ResultSet rs) throws Exception {

		ProductoDTOImpl ret = //
			(ProductoDTOImpl) dtaSession.getDtaByKey( //
					ProductoDTOImpl.class, rs.getInt(ProductoDTOImpl.ID));

		if (ret != null) {
			return ret;
		}

		if (rs.getString("dtoClass").equals(ArmaDTO.class.getName())) {
			ArmaDAO armaDAO = (ArmaDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaDAO.class, connectionBean);

			ret = (ProductoDTOImpl) armaDAO.loadById( //
					rs.getInt(ProductoDTO.ID));

			return (ProductoDTOImpl) dtaSession.add(ret);
		}

		if (rs.getString("dtoClass").equals(ArmaduraDTO.class.getName())) {
			ArmaduraDAO armaduraDAO = (ArmaduraDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaduraDAO.class, connectionBean);

			ret = (ProductoDTOImpl) armaduraDAO.loadById( //
					rs.getInt(ProductoDTO.ID));

			return (ProductoDTOImpl) dtaSession.add(ret);
		}

		if (rs.getString("dtoClass").equals(PocionDTO.class.getName())) {
			PocionDAO pocionDAO = (PocionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					PocionDAO.class, connectionBean);

			ret = (ProductoDTOImpl) pocionDAO.loadById( //
					rs.getInt(ProductoDTO.ID));

			return (ProductoDTOImpl) dtaSession.add(ret);
		}

		if (rs.getString("dtoClass").equals(AvionDTO.class.getName())) {
			AvionDAO avionDAO = (AvionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					AvionDAO.class, connectionBean);

			ret = (ProductoDTOImpl) avionDAO.loadById( //
					rs.getInt(ProductoDTO.ID));

			return (ProductoDTOImpl) dtaSession.add(ret);
		}


		throw new IllegalArgumentException(rs.getString("dtoClass"));
	}

	//-------------------------------------------------------------------
	//		Insert
	//-------------------------------------------------------------------

	@Override
	public void insert(IDTO dto) throws Exception {
		if (dto instanceof ArmaDTO) {
			ArmaDAO armaDAO = (ArmaDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaDAO.class, connectionBean);

			armaDAO.insert(dto);

			return;
		}

		if (dto instanceof ArmaduraDTO) {
			ArmaduraDAO armaduraDAO = (ArmaduraDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaduraDAO.class, connectionBean);

			armaduraDAO.insert(dto);

			return;
		}

		if (dto instanceof PocionDTO) {
			PocionDAO pocionDAO = (PocionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					PocionDAO.class, connectionBean);

			pocionDAO.insert(dto);

			return;
		}

		if (dto instanceof AvionDTO) {
			AvionDAO avionDAO = (AvionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					AvionDAO.class, connectionBean);

			avionDAO.insert(dto);

			return;
		}

		// ---------------------------------------------
		// Others if (dto instanceof xxxDTO) if required
		// ---------------------------------------------
	}

	//-------------------------------------------------------------------
	//		Update
	//-------------------------------------------------------------------	
	@Override
	public void update(IDTO dto) throws Exception {
		if (dto instanceof ArmaDTO) {
			ArmaDAO armaDAO = (ArmaDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaDAO.class, connectionBean);

			armaDAO.update(dto);

			return;
		}

		if (dto instanceof ArmaduraDTO) {
			ArmaduraDAO armaduraDAO = (ArmaduraDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaduraDAO.class, connectionBean);

			armaduraDAO.update(dto);

			return;
		}

		if (dto instanceof PocionDTO) {
			PocionDAO pocionDAO = (PocionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					PocionDAO.class, connectionBean);

			pocionDAO.update(dto);

			return;
		}

		if (dto instanceof AvionDTO) {
			AvionDAO avionDAO = (AvionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					AvionDAO.class, connectionBean);

			avionDAO.update(dto);

			return;
		}

		// ---------------------------------------------
		// Others if (dto instanceof xxxDTO) if required
		// ---------------------------------------------
	}

	//-------------------------------------------------------------
	//		Delete
	//-------------------------------------------------------------	
	@Override
	public void delete(IDTO dto) throws Exception {
		if (dto instanceof ArmaDTO) {
			ArmaDAO armaDAO = (ArmaDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaDAO.class, connectionBean);

			armaDAO.delete(dto);

			return;
		}

		if (dto instanceof ArmaduraDTO) {
			ArmaduraDAO armaduraDAO = (ArmaduraDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					ArmaduraDAO.class, connectionBean);

			armaduraDAO.delete(dto);

			return;
		}

		if (dto instanceof PocionDTO) {
			PocionDAO pocionDAO = (PocionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					PocionDAO.class, connectionBean);

			pocionDAO.delete(dto);

			return;
		}

		if (dto instanceof AvionDTO) {
			AvionDAO avionDAO = (AvionDAO) //
			AbstractFactoryDAO.getFactoryDAO().getDAO( //
					AvionDAO.class, connectionBean);

			avionDAO.delete(dto);

			return;
		}

		// ---------------------------------------------
		// Others if (dto instanceof xxxDTO) if required
		// ---------------------------------------------
	}

	//---------------------------------------------------------------------------	
	@Override
	public List<IDTO> listAll(int lim, int off) throws Exception {

		ArmaDAO armaDAO = (ArmaDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				ArmaDAO.class, connectionBean);

		ArmaduraDAO armaduraDAO = (ArmaduraDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				ArmaduraDAO.class, connectionBean);

		PocionDAO pocionDAO = (PocionDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				PocionDAO.class, connectionBean);

		AvionDAO avionDAO = (AvionDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				AvionDAO.class, connectionBean);

		StringBuffer strbuf = new StringBuffer();

		// SELECT producto.*, 'bdsimple.base.ArmaDTO' AS dtoClass FROM
		//   producto, arma
		//   WHERE
		//     arma.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				ArmaDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + armaDAO.getTableName());
		strbuf.append(" WHERE  " + //
				armaDAO.getTableName() + "." + ArmaDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);

		strbuf.append(" UNION ");

		// SELECT producto.*, 'bdsimple.base.ArmaduraDTO' AS dtoClass FROM
		//   producto, armadura
		//   WHERE
		//     armadura.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				ArmaduraDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + armaduraDAO.getTableName());
		strbuf.append(" WHERE  " + //
				armaduraDAO.getTableName() + "." + ArmaduraDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);

		strbuf.append(" UNION ");

		// SELECT producto.*, 'bdsimple.base.PocionDTO' AS dtoClass FROM
		//   producto, pocion
		//   WHERE
		//     pocion.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				PocionDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + pocionDAO.getTableName());
		strbuf.append(" WHERE  " + //
				pocionDAO.getTableName() + "." + PocionDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);

		strbuf.append(" UNION ");

		// SELECT producto.*, 'bdsimple.base.AvionDTO' AS dtoClass FROM
		//   producto, avion
		//   WHERE
		//     avion.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				AvionDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + avionDAO.getTableName());
		strbuf.append(" WHERE  " + //
				avionDAO.getTableName() + "." + AvionDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);


		if (lim >= 0 && off >= 0) {
			strbuf.append(" LIMIT  ");
			strbuf.append(lim);
			strbuf.append(" OFFSET ");
			strbuf.append(off);
		}

		System.err.println(strbuf.toString());

		ResultSet rs = //
			connection.createStatement().executeQuery(strbuf.toString());

		List<IDTO> ret = new ArrayList<IDTO>();

		while (rs.next()) {
			ret.add(resultSetToDTO(rs));
		}

		return ret;
	}

	//---------------------------------------------------------------------------------	
	@Override
	public List<IDTO> listBy(String key, Object val) throws Exception {
		ArmaDAO armaDAO = (ArmaDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				ArmaDAO.class, connectionBean);

		ArmaduraDAO armaduraDAO = (ArmaduraDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				ArmaduraDAO.class, connectionBean);

		PocionDAO pocionDAO = (PocionDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				PocionDAO.class, connectionBean);

		AvionDAO avionDAO = (AvionDAO) //
		AbstractFactoryDAO.getFactoryDAO().getDAO( //
				AvionDAO.class, connectionBean);

		StringBuffer strbuf = new StringBuffer();

		// SELECT producto.*, 'bdsimple.base.ArmaDTO' AS dtoClass FROM
		//   producto, arma
		//   WHERE
		//     arma.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				ArmaDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + armaDAO.getTableName());
		strbuf.append(" WHERE  " + //
				armaDAO.getTableName() + "." + ArmaDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);
		strbuf.append(" AND ");
		strbuf.append(key);
		strbuf.append(" = ");
		strbuf.append(val);

		strbuf.append(" UNION ");

		// SELECT producto.*, 'bdsimple.base.ArmaduraDTO' AS dtoClass FROM
		//   producto, armadura
		//   WHERE
		//     armadura.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				ArmaduraDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + armaduraDAO.getTableName());
		strbuf.append(" WHERE  " + //
				armaduraDAO.getTableName() + "." + ArmaduraDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);
		strbuf.append(" AND ");
		strbuf.append(key);
		strbuf.append(" = ");
		strbuf.append(val);

		strbuf.append(" UNION ");

		// SELECT producto.*, 'bdsimple.base.PocionDTO' AS dtoClass FROM
		//   producto, pocion
		//   WHERE
		//     pocion.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				PocionDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + pocionDAO.getTableName());
		strbuf.append(" WHERE  " + //
				pocionDAO.getTableName() + "." + PocionDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);
		strbuf.append(" AND ");
		strbuf.append(key);
		strbuf.append(" = ");
		strbuf.append(val);

		strbuf.append(" UNION ");

		// SELECT producto.*, 'bdsimple.base.AvionDTO' AS dtoClass FROM
		//   producto, avion
		//   WHERE
		//     avion.id == producto.id
		strbuf.append("SELECT " + getTableName() + ".*, '" + //
				AvionDTO.class.getName() + "' AS dtoClass FROM ");

		strbuf.append(this.getTableName() + ", " + avionDAO.getTableName());
		strbuf.append(" WHERE  " + //
				avionDAO.getTableName() + "." + AvionDTO.ID + //
				" = " + //
				this.getTableName() + "." + ProductoDTO.ID);
		strbuf.append(" AND ");
		strbuf.append(key);
		strbuf.append(" = ");
		strbuf.append(val);

		//---------------------------------------------------------------
		System.err.println(strbuf.toString());

		ResultSet rs = //
			connection.createStatement().executeQuery(strbuf.toString());

		List<IDTO> ret = new ArrayList<IDTO>();

		while (rs.next()) {
			ret.add(resultSetToDTO(rs));
		}

		return ret;

	}


	public byte[] loadImageByItemId(int articuloId) throws SQLException {
		StringBuffer strbuf = new StringBuffer();

		strbuf.append("SELECT ");
		strbuf.append(ItemDTO.IMAGEN);
		strbuf.append(" FROM ");
		strbuf.append(getTableName());
		strbuf.append(" WHERE ");
		strbuf.append(ItemDTO.ID);
		strbuf.append(" = ");
		strbuf.append(articuloId);

		System.err.println(strbuf.toString());

		ResultSet rs = //
			connection.createStatement().executeQuery(strbuf.toString());

		if (rs.next()) {
			return rs.getBytes(ItemDTO.IMAGEN);
		}

		return null;
	}
	
	public List<ItemDTO> listByCiudadId(int id) throws Exception { 
        StringBuffer strbuf = new StringBuffer();

        PrecioItemCiudadDAOImpl ciudadArticuloDAO = new PrecioItemCiudadDAOImpl();
        ItemDAO articuloDAOImpl = new ItemDAOImpl();

        strbuf.append("SELECT " + getTableName() + ".* FROM ");
        strbuf.append(getTableName());
        strbuf.append(" JOIN " + ciudadArticuloDAO.getTableName());
        strbuf.append(" ON " + articuloDAOImpl.getTableName() + "." + ItemDTO.ID + " = " + PrecioItemCiudadDTO.ITEM_REFERENCIA);
        strbuf.append(" WHERE " + PrecioItemCiudadDTO.CIUDAD_REFERENCIA + " = " + id);

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        List<ItemDTO> ret = new ArrayList<ItemDTO>();

        while (rs.next()) {
            ret.add(resultSetToDTO(rs));
        }

        return ret;
    }
	
}
